package com.itheima.stock.service.impl;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.stock.common.domain.*;
import com.itheima.stock.mapper.SysUserMapper;
import com.itheima.stock.pojo.StockBlockRtInfo;
import com.itheima.stock.pojo.SysUser;
import com.itheima.stock.service.StockUserService;
import com.itheima.stock.utils.DateTimeUtil;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.vo.req.LoginReqVo;
import com.itheima.stock.vo.resp.LoginRespVo;
import com.itheima.stock.vo.resp.PageResult;
import com.itheima.stock.vo.resp.R;
import com.itheima.stock.vo.resp.ResponseCode;
import org.apache.commons.lang3.RandomStringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class StockUserServiceImpl implements StockUserService {
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private StockInfoConfig stockInfoConfig;
    @Override
    public R<LoginRespVo> login(LoginReqVo reqVo) {
        //判断请求的数据 以及用户名和密码是否存在 验证码是否存在 唯一标识是否存在  响应参数异常
        if (reqVo == null || reqVo.getUsername() ==null || reqVo.getPassword()==null || reqVo.getCode()==null || reqVo.getRkey()==null) {
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        //查询验证码是和否正确
        String code = redisTemplate.opsForValue().get(reqVo.getRkey());
        assert code != null;
        if (!code.equals(reqVo.getCode())){
            redisTemplate.delete(reqVo.getRkey());
            return R.error(ResponseCode.SYSTEM_VERIFY_CODE_ERROR.getMessage());
        }
        //删除redis中的数据
        redisTemplate.delete(reqVo.getRkey());
        //从数据库查询 为空或者密码不匹配响应账号或密码错误
        SysUser sysUser= sysUserMapper.selectByUsername(reqVo.getUsername());
        if (sysUser==null || !passwordEncoder.matches(reqVo.getPassword(),sysUser.getPassword())) {
            return R.error(ResponseCode.SYSTEM_PASSWORD_ERROR.getMessage());
        }
        //登陆成功创建对象
        LoginRespVo respVo = new LoginRespVo();
        BeanUtils.copyProperties(sysUser,respVo);
        return R.ok(respVo);
    }

    @Override
    public R<Map<String, String>> captcha() {
        //获得验证码
        String code = RandomStringUtils.randomNumeric(4);
        //获得唯一标识
        String value = String.valueOf(idWorker.nextId());
        //存入redis中
        redisTemplate.opsForValue().set(value,code,60, TimeUnit.SECONDS);
        //响应给前端
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("code",code);
        hashMap.put("rkey",value);
        return R.ok(hashMap);

    }

    @Override
    public R<List<InnerMarketDomain>> stockmarket() {
        //获取当前最接近当前时间的交易时间
        DateTime dateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        String curTime = dateTime.toString(DateTimeFormat.forPattern("yyyyMMddHHmmss"));
        //测试数据
        curTime= "20211228113000";
        ArrayList<String> list = new ArrayList<>();
        //根据这个时间和大盘id查询
        List<InnerMarketDomain> stockMarket = sysUserMapper.stockmarket(stockInfoConfig.getInner(),curTime);
        //返回结果
        return R.ok(stockMarket);
    }

    @Override
    public R<List<StockBlockRtInfo>> stockBlockRtInfo() {
        //获取当前最新的交易日日期
        DateTime dateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        String curTime = dateTime.toString(DateTimeFormat.forPattern("yyyyMMdd"));
        //测试数据
        curTime="20220114";
        //查询数据库
        List<StockBlockRtInfo> list = sysUserMapper.stockBlockRtInfo(curTime);
        System.out.println(list);

        return R.ok(list);
    }

    @Override
    public R<List<StockUpdownDomain>> increase() {
        //获取最新的交易时间
        DateTime dateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        String curTime = dateTime.toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm"));
        //测试数据
        curTime= "2021-12-28 11:30:00";
        //查询
        ArrayList<StockUpdownDomain> list = sysUserMapper.increase(curTime);
        return R.ok(list);
    }

    @Override
    public R<PageResult<StockUpdownDomain>> stockAll(Integer page,Integer pageSize) {
        //设置分页参数
        PageHelper.startPage(page,pageSize);
        //查询
        List<StockUpdownDomain> stockAll = sysUserMapper.stockAll(page,pageSize);
        //判断
        if (stockAll==null){
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        //封装
        PageInfo<StockUpdownDomain> stockUpdownDomainPageInfo = new PageInfo<>(stockAll);
        PageResult<StockUpdownDomain> stockUpdownDomainPageResult = new PageResult<>(stockUpdownDomainPageInfo);
        return R.ok(stockUpdownDomainPageResult);
    }

    @Override
    public R<Map<String,List<Map<String,String>>>>  stockUpdownCount() {
        //首先根据当前日期找一个日期范围
        //获取最新的交易日期
        DateTime dateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //获取范围
        String openDate = DateTimeUtil.getOpenDate(dateTime).toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm"));
        String closeDate = DateTimeUtil.getCloseDate(dateTime).toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm"));
        //测试数据
        openDate="2022-01-06 09:25:00";
        closeDate="2022-01-06 14:25:00";
        //根据这个范围查询
        //跌停为0,涨停为1
        List<Map<String,String>> downList =  sysUserMapper.stockUpdownCount(openDate,closeDate,0);
        System.out.println("downList = " + downList);
        List<Map<String,String>> upList = sysUserMapper.stockUpdownCount(openDate,closeDate,1);
        System.out.println("upList = " + upList);
        //封装数据
        HashMap<String, List<Map<String, String>>> data = new HashMap<>();
        data.put("upList",upList);
        data.put("downList",downList);
        System.out.println("data = " + data);
        return R.ok(data);

    }

    @Override
    public void export(HttpServletResponse response,Integer page, Integer pageSize) throws IOException {
        //1.设置响应数据的类型:excel
        response.setContentType("application/vnd.ms-excel");
        //2.设置响应数据的编码格式
        response.setCharacterEncoding("utf-8");
        //3.设置默认的文件名称
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("stockRt", "UTF-8");
        //设置默认文件名称
        response.setHeader("content-disposition", "attachment;filename=" + fileName + ".xlsx");
        //4.分页查询股票数据
        PageHelper.startPage(page,pageSize);
        //查询
        List<StockUpdownDomain> stockAll = sysUserMapper.stockAll(page,pageSize);
        //判断
        if (stockAll==null){
            response.getWriter().print(ResponseCode.NO_RESPONSE_DATA);
        }
        //导出表格
        EasyExcel.write(response.getOutputStream(),StockUpdownDomain.class).sheet("股票数据").doWrite(stockAll);

    }

    @Override
    public R<Map<String, List<Map<String, String>>>> tradevol() {
        //获取当前最近的交易日期
        DateTime day = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //获取当前最近的交易日期的前一天
        DateTime yesterday = DateTimeUtil.getPreviousTradingDay(day);
        //获取当前最近交易日期的开盘时间和收盘时间
        Date openDate = DateTimeUtil.getOpenDate(day).toDate();
        Date closeDate = DateTimeUtil.getCloseDate(day).toDate();
        //获取当前最近交易日期的前一天的开盘时间和收盘时间
        Date preOpenDate = DateTimeUtil.getOpenDate(yesterday).toDate();
        Date preCloseDate = DateTimeUtil.getCloseDate(yesterday).toDate();
        //获取国内A股大盘的id
        List<String> inner = stockInfoConfig.getInner();
        // 测试数据
        String preTStr="20211229150000";
        closeDate = DateTime.parse(preTStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        String openDateStr2="20211228150000";
        preCloseDate= DateTime.parse(openDateStr2, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        String tDateStr="20211229093000";
        openDate = DateTime.parse(tDateStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        String openDateStr="20211228093000";
        preOpenDate = DateTime.parse(openDateStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        //根据数据查询当天的交易信息
        List<Map<String,String>> volList = sysUserMapper.tradevol(inner,openDate,closeDate);
        //根据数据查询前一天的交易信息
        List<Map<String,String>> yesVolList = sysUserMapper.tradevol(inner,preOpenDate,preCloseDate);
        //封装数据
        HashMap<String, List<Map<String, String>>> map = new HashMap<>();
        map.put("volList",volList);
        map.put("yesVolList",yesVolList);
        return R.ok(map);
    }

    @Override
    public R<Map<Map<String, String>, Map<String,List<Map<String, String>>>>> updown() {
        //获取当前最近的交易时间点
        DateTime lastDate4Stock = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date date = lastDate4Stock.toDate();
        String time = lastDate4Stock.toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm"));

        //根据最近时间点查询
        List<Map<String,String>> maplist = sysUserMapper.updown(date);
        //封装数据
        HashMap<String, String> hashMap = new HashMap<>();
        HashMap<String, List<Map<String, String>>> infos = new HashMap<>();
        List<String> upDownRange = stockInfoConfig.getUpDownRange();
        List<Map<String,String>> mapList = upDownRange.stream().map(key -> {
            Optional<Map<String, String>> title = maplist.stream().filter(map -> key.equals(map.get("title"))).findFirst();
            //判断对应的map是否存在
            Map<String,String> tmp = null;
            if (title.isPresent()) {
                tmp = title.get();
            } else {
                tmp = new HashMap<String,String>();
                tmp.put("title", key);
                tmp.put("count", "0");
            }
            return tmp;
        }).collect(Collectors.toList());
        infos.put("infos",mapList);
        hashMap.put("time",time);
        HashMap<Map<String, String>, Map<String,List<Map<String, String>>>> map = new HashMap<>();
        map.put(hashMap,infos);
        return R.ok(map);
    }

    @Override
    public R<List<Stock4MinuteDomain>> timeSharing(String code) {
        //获取最近交易日期
        String date = DateTimeUtil.getLastDate4Stock(DateTime.now()).toString(DateTimeFormat.forPattern("YYYYmmdd"));
        //根据日期查询
        //假数据
        date="20211230";
        List<Stock4MinuteDomain> list = sysUserMapper.timeSharing(date,code);
        //封装数据
        if(list==null){
         return R.ok(new ArrayList<Stock4MinuteDomain>(){});
        }
        return R.ok(list);
    }

    @Override
    public R<List<Stock4EvrDayDomain>> dkline(String code) {
        //获取最近交易日
        DateTime lastDay = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //获取往前20天
        DateTime openDay = lastDay.minusDays(20);
        //格式化
        String lastDay1 = lastDay.toString(DateTimeFormat.forPattern("YYYYmmdd"));
        String openDay1 = openDay.toString(DateTimeFormat.forPattern("YYYYmmdd"));
        //假数据
        lastDay1="20220120";
        openDay1="20211230";
        //根据日期查询当前收盘时间集合
        List<String> closePrice = sysUserMapper.getClosePrice(openDay1,lastDay1,code);
        System.out.println(closePrice);
        //根据收盘日期集合查询结果集
        List<Stock4EvrDayDomain> list = sysUserMapper.getClosePrice2(closePrice,code);
        return R.ok(list);
    }

}
